package Order.Serializer;

import Order.DAO.CustomerDAO;
import Order.DAO.OrderDAO;
import Order.DAO.ProductDAO;
import Order.Entity.Customer;
import Order.Entity.Order;
import Order.Entity.OrderLine;
import Order.Entity.Product;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.swing.plaf.basic.BasicSliderUI.ActionScroller;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

public class OrderSerializer {

    private static final String PERSISTENCE_UNIT_NAME = "OrderEntityPU";
    private EntityManagerFactory factory;
    private EntityManager em;
    private CustomerDAO customerDAO;
    private OrderDAO orderDAO;
    private ProductDAO productDAO;

    public OrderSerializer() {
        factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
            em = factory.createEntityManager();
            customerDAO = new CustomerDAO(em);
            orderDAO = new OrderDAO(em);
            productDAO = new ProductDAO(em);
    }
    static JAXBContext context = null;

    public void exportToXML(Order order, String address) {
        File file = new File(address);
        OutputStream stream = null;
        try {
            stream = new FileOutputStream(file);
            this.createXMLDocument(order, stream);
        } catch (FileNotFoundException ex) {
            Logger.getLogger(OrderSerializer.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                stream.close();
            } catch (IOException ex) {
                Logger.getLogger(OrderSerializer.class.getName()).log(Level.WARNING, null, ex);
            }
        }
    }

    public void createXMLDocument(Order order, OutputStream stream) {
        try {
            context = JAXBContext.newInstance("Order.Serializer");
            Marshaller marshaller = context.createMarshaller();
            em.getTransaction().begin();

            OrderType purchaseOrder = new OrderType();
            purchaseOrder.setAction(order.getAction());
            purchaseOrder.setID(order.getId());
            if (order.getAction().contains("new")) {
                NewOrderType newOrderType = new NewOrderType();
                newOrderType.setIssueDate(order.getCreateDate());
                newOrderType.setStatus(order.getStatus());
                newOrderType.setTotal(order.getTotal().toString());

                CustomerPartyType customerPartyType = new CustomerPartyType();

                Customer customer = order.getCustomer();
                if (customer != null) {
                    customerPartyType.setID(customer.getId());
                    customerPartyType.setName(customer.getName());
                    customerPartyType.setAddress(customer.getAddress());
                    customerPartyType.setContact(customer.getContact().toString());
                }
                newOrderType.setCustomerParty(customerPartyType);

                for (OrderLine orderline : (List<OrderLine>) order.getOrderlines()) {
                    OrderLineType orderlineType = new OrderLineType();
                    orderlineType.setOrderLineNumber(orderline.getId());
                    orderlineType.setQuantity(orderline.getQuantity());

                    ItemType itemType = new ItemType();

                    Product product = new Product();
                    product = productDAO.FindById(orderline.getProduct().getId());
                    itemType.setProductId(product.getId());
                    itemType.setProductName(product.getDescription());
                    itemType.setPrice(product.getPrice().toString());
                    orderlineType.setItem(itemType);

                    newOrderType.getOrderLine().add(orderlineType);
                }
                purchaseOrder.setNewOrder(newOrderType);
            } else if (order.getAction().contains("change")) {
                ChangeOrderType changeOrderType = new ChangeOrderType();
                for (OrderLine orderline : (List<OrderLine>) order.getOrderlines()) {
                    OrderLineType orderlineType = new OrderLineType();
                    orderlineType.setAction(orderline.getAction());
                    orderlineType.setOrderLineNumber(orderline.getId());
                    orderlineType.setQuantity(orderline.getQuantity());
                    ItemType itemType = new ItemType();

                    Product product = new Product();
                    product = productDAO.FindById(orderline.getProduct().getId());
                    itemType.setProductId(product.getId());
                    itemType.setProductName(product.getDescription());
                    itemType.setPrice(product.getPrice().toString());
                    orderlineType.setItem(itemType);

                    changeOrderType.getOrderLine().add(orderlineType);
                }
                purchaseOrder.setChangeOrder(changeOrderType);
            }
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
            marshaller.marshal(purchaseOrder, stream);

            // Commit the transaction, which will cause the entity to
            // be stored in the database
            em.getTransaction().commit();
        } catch (JAXBException e) {
            Logger.getLogger(OrderSerializer.class.getName()).log(Level.SEVERE, null, e);
            System.out.println(e.toString());
            em.getTransaction().rollback();
        } catch (Exception e) {
            em.getTransaction().rollback();
        } finally {
            // It is always good practice to close the EntityManager so that
            // resources are conserved.
            em.close();
        }
    }

    public String update(String request) throws Exception{
        ResponseOrderType response = new ResponseOrderType();

        InputStream stream = new ByteArrayInputStream(request.getBytes());
        OutputStream oStream = new ByteArrayOutputStream();

        //perform the logic
     
            Order order = this.importXML(stream);
            
            if(order != null)
            {
            response.setAcceptedIndicator(true);
            }
            else
            {
            response.setAcceptedIndicator(false);
            }
        

        //perform the xml display
        try {
            context = JAXBContext.newInstance("Order.Serializer");
            Marshaller marshaller = context.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
            marshaller.marshal(response, oStream);
        } catch (JAXBException ex) {
            Logger.getLogger(OrderSerializer.class.getName()).log(Level.SEVERE, null, ex);
        }
        return oStream.toString();

    }

    public Order importXML(String address) throws Exception {
        File xmlDocument = new File(address);
        Order order = null;
        FileInputStream fileInputStream = null;
        try {
            fileInputStream = new FileInputStream(xmlDocument);
            order = importXML(fileInputStream);
        } catch (FileNotFoundException ex) {
            Logger.getLogger(OrderSerializer.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                if (fileInputStream != null) {
                    fileInputStream.close();
                }
            } catch (IOException ex) {
                Logger.getLogger(OrderSerializer.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return order;
    }

    public Order importXML(InputStream stream) throws Exception{
        Order order = new Order();
 //       try {

            em.getTransaction().begin();

            context = JAXBContext.newInstance("Order.Serializer");

            Unmarshaller unmarshaller = context.createUnmarshaller();
            OrderType orderType = (OrderType) unmarshaller.unmarshal(stream);

            if(orderType.getAction().contains("new"))
            {
             
            NewOrderType newOrderType = orderType.getNewOrder();
            order.setAction(orderType.getAction());
            order.setId(orderType.getID());
            order.setCreateDate(newOrderType.getIssueDate());
            Customer customer = customerDAO.FindById(newOrderType.getCustomerParty().getID());
            order.setCustomer(customer);
            order.setTotal(Integer.parseInt(newOrderType.getTotal()));
            order.setStatus(newOrderType.getStatus());

            for (OrderLineType orderLineType : newOrderType.getOrderLine()) {
                OrderLine orderline = new OrderLine();
                orderline.setOrder(order);
                orderline.setId(orderLineType.getOrderLineNumber());
                orderline.setQuantity(orderLineType.getQuantity());
                Product product = productDAO.FindById(orderLineType.getItem().getProductId());
                orderline.setProduct(product);

                order.addOrderline(orderline);
            }
            orderDAO.persist(order);
            }
             else if (orderType.getAction().contains("change")) {
                 ChangeOrderType changeOrderType = orderType.getChangeOrder();
            for (OrderLineType orderLineType : changeOrderType.getOrderLine()) {
                OrderLine orderline = new OrderLine();
                orderline.setOrder(order);
                orderline.setId(orderLineType.getOrderLineNumber());
                orderline.setQuantity(orderLineType.getQuantity());
                Product product = productDAO.FindById(orderLineType.getItem().getProductId());
                orderline.setProduct(product);

                order.addOrderline(orderline);
            }

                orderDAO.merge(order);
            } else if (orderType.getAction().contains("cancel")) {
                order = orderDAO.FindById(orderType.getID());
                orderDAO.remove(order);
            } else if (orderType.getAction().contains("retrieve")) {
                orderDAO.FindById(order.getId());
            }


            // Commit the transaction, which will cause the entity to
            // be stored in the database
            em.getTransaction().commit();
//        } catch (JAXBException e) {
//            Logger.getLogger(OrderSerializer.class.getName()).log(Level.SEVERE, null, e);
//            System.out.println(e.toString());
//            em.getTransaction().rollback();
//        } catch (Exception e) {
//            em.getTransaction().rollback();
//        } finally {
//            // It is always good practice to close the EntityManager so that
//            // resources are conserved.
//            em.close();
//        }
        return order;
    }
}
